from farstyle import settings

import os
import md5

def get_filter(filter_class):
    """
    Convert a string version of a function name to the callable object.
    """
    if not hasattr(filter_class, '__bases__'):
        try:
            filter_class = filter_class.encode('ascii')
            mod_name, class_name = get_mod_func(filter_class)
            if class_name != '':
                filter_class = getattr(__import__(mod_name, {}, {}, ['']), class_name)
        except (ImportError, AttributeError):
            raise Exception('Failed to import filter %s' % filter_class)

    return filter_class

def get_mod_func(callback):
    """
    Convert 'django.views.news.stories.story_detail' to
    ('django.views.news.stories', 'story_detail').
    """
    try:
        dot = callback.rindex('.')
    except ValueError:
        return callback, ''
    return callback[:dot], callback[dot+1:]

def filter(data, filters, attr):
    output = data
    for f in filters:
        output = getattr(get_filter(f)(), attr)(output)

    return output

def filter_css(css, filters=settings.CSS_FILTERS):
    return filter(css, filters=filters, attr='filter_css')

def filter_js(js, filters=settings.JS_FILTERS):
    return filter(js, filters=filters, attr='filter_js')

def combine(group, context, type):
    assets = group['assets']
    control = [ asset.ident(context) for asset in assets ]
    m = md5.new()
    m.update(u' '.join(control))
    digest = m.hexdigest()
    fname = os.path.join(settings.ASSETS_DIR, 'asset_%s.%s' % (digest, type))
    fpath = os.path.join(settings.MEDIA_ROOT, fname)
    if not os.path.exists(fpath):
        data = u'\n'.join([ asset.render() for asset in assets ])
        filters = getattr(settings, type.upper() + '_FILTERS')
        data = filter(data, filters=filters, attr='filter_' + type)
        out = open(fpath, 'wb')
        out.write(data.encode('utf-8'))
        out.close()

    return '%s/asset_%s.%s' % (settings.ASSETS_DIR, digest, type)

def combine_js(group, context):
    return combine(group, context, 'js')

def combine_css(group, context):
    return combine(group, context, 'css')
